#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
#include <cassert>
#include <fstream>
#include "../comm/Log.hpp"
#include "../comm/util.hpp"

namespace ns_model
{
    using namespace ns_util;

    const std::string questions_list = "./questions/questions_list";
    const std::string question_path = "./questions/";

    struct Question
    {
        std::string num;    // 题目编号
        std::string title;  // 题目标题
        std::string level;  // 题目难度等级
        int cpu_limit;      // 题目时间限制 单位 s
        int mem_limit;      // 题目内存限制 单板 byte
        std::string desc;   // 题目描述
        std::string header; // 用户需要用到的头文件
        std::string body;   // 显示给用户的代码
        std::string tail;   // 用来测试用户的代码
    };

    class Model
    {
    public:
        Model()
        {
            // 将题目列表中的题目加载到questions容器中
            assert(LoadQuestionsList(questions_list));
        }
        bool LoadQuestionsList(const std::string &questions_list)
        {
            // 加载到questions_list文件
            std::ifstream in(questions_list, std::ifstream::in);
            if (!in.is_open())
            {
                LOG(FATAL, "questions_list 配置文件打开失败");
                return false;
            }
            std::string line;
            while (getline(in, line))
            {
                // 对line进行切割
                // 1 找出最大数 简单 1 10000000
                std::vector<std::string> tokens;
                StringUtil::Spilit(line, tokens, " ");
                if (tokens.size() != 5)
                {
                    LOG(WARNING, "部分题目加载失败");
                    continue;
                }
                Question q;
                q.num = tokens[0];
                q.title = tokens[1];
                q.level = tokens[2];
                q.cpu_limit = std::stoi(tokens[3]);
                q.mem_limit = std::stoi(tokens[4]);

                std::string path = question_path + "/" + q.num + "/";

                q.desc = FileUtil::ReadFile(path + "desc.txt");
                q.header = FileUtil::ReadFile(path + "header.hpp");
                q.body = FileUtil::ReadFile(path + "body.cc");
                q.tail = FileUtil::ReadFile(path + "tail.cc");

                _questions.insert({q.num, q});
            }
            LOG(INFO, "加载题库成功");
            in.close();
        }
        bool GetAllQuestions(std::vector<Question> &v)
        {
            if (_questions.size() == 0)
            {
                LOG(ERROR, "题目为空");
                return false;
            }
            for (auto &e : _questions)
            {
                v.push_back(e.second);
            }

            return true;
        }
        bool GetOneQuestionByNumber(const std::string &number, Question &question)
        {
            auto iter = _questions.find(number);
            if (iter == _questions.end())
            {
                LOG(ERROR, "获取题目失败");
                return false;
            }
            question = iter->second;

            return true;
        }

    private:
        std::unordered_map<std::string, Question> _questions; // 题目编号和题目的映射关系
    };
}